﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Security.Cryptography;

namespace IPlugin
{
    public static class Sessions
    {
        public static List<Session> lstSessions = new List<Session>();

        public static void AddSession(Session session)
        {
            bool locked = false;
            try
            {
                System.Threading.Monitor.Enter(lstSessions, ref locked);
                lstSessions.Add(session);
            }
            catch
            {
                Console.WriteLine("Error creating session");
            }
            finally
            {
                 if (locked)
                     System.Threading.Monitor.Exit(lstSessions);
            }
        }

        public static Session GetSession(string hash)
        {
            bool locked = false;
            try
            {
                System.Threading.Monitor.Enter(lstSessions, ref locked);

                foreach (Session session in lstSessions)
                {
                    if (session.hash == hash)
                        return session;
                }
            }
            finally
            {
                if (locked)
                    System.Threading.Monitor.Exit(lstSessions);
            }

            return null;
        }

        public static Session GetSession(Model.Elements.HttpRequestPacket request)
        {
            foreach (Model.Elements.HttpHeader header in request.lstHeaders)
            {
                if (header.name.ToLower() == "cookie")
                {
                    Model.Elements.SingleCookieHeader[] singleCookieList = Model.Elements.SingleCookieHeader.Parse(header.value);
                    foreach (Model.Elements.SingleCookieHeader cookie in singleCookieList)
                    {
                        if (cookie.name == Configuration.Configuration.cookieSessionName)
                        {
                            Session session = Sessions.GetSession(cookie.value);

                            if (session != null)
                                return session;
                        }
                    }

                    /*
                    if (singleCookie == null)
                        continue;

                    if (singleCookie.name == Configuration.Configuration.cookieSessionName)
                    {
                        Session session = Sessions.GetSession(singleCookie.value);

                        if (session != null)
                            return session;
                    }
                    */
                }
            }

            return null;
        }

        public static void RemoveSession(Session session)
        {
            bool locked = false;
            try
            {
                System.Threading.Monitor.Enter(lstSessions, ref locked);
                lstSessions.Remove(session);
            }
            catch
            {

            }
            finally
            {
                if (locked)
                    System.Threading.Monitor.Exit(lstSessions);
            }
        }

        public static void RemoveSession(string hash)
        {
            bool locked = false;
            try
            {
                System.Threading.Monitor.Enter(lstSessions, ref locked);

                for (int i = 0; i < lstSessions.Count; i++)
                {
                    Session s = (Session)lstSessions[i];
                    if (s.hash == hash)
                    {
                        lstSessions.RemoveAt(i);
                        break;
                    }
                }
            }
            catch
            {

            }
            finally
            {
                if (locked)
                    System.Threading.Monitor.Exit(lstSessions);
            }
        }

        public static bool ExistsSession(string hash)
        {
            for (int i = 0; i < lstSessions.Count; i++)
            {
                if (lstSessions[i].hash == hash)
                    return true;
            }

            return false;
        }

        public static Session GenerateSession()
        {
            SHA512 sha512 = SHA512.Create();
            StringBuilder random = new StringBuilder();
            Random r = new Random();

            for (int i = 0; i < 10; i++)
            {
                random.Append(r.Next(0, 65000));
                random.Append(DateTime.Now.Ticks);
                random.Append(r.Next(0, 65000));
                random.Append(DateTime.Now.Ticks);
            }

            Session s = new Session(BitConverter.ToString(sha512.ComputeHash(Encoding.UTF8.GetBytes(random.ToString()))).Replace("-",""));
            return s;
        }
    }

    public class Session
    {
        public string hash = string.Empty;
        public Hashtable elements = new Hashtable();

        public Session(string hash)
        {
            this.hash = hash;
        }

        public Object GetObjectByTagName(string tagName)
        {
            return elements[tagName];
        }

        public void SetObjectByName(string tagName, object o)
        {
            elements[tagName] = o;
        }

        public DictionaryEntry[] GetObjects()
        {
            DictionaryEntry[] objects = new DictionaryEntry[elements.Count];

            int i = 0;

            foreach (DictionaryEntry o in elements)
            {
                objects[i] = o;
                i++;
            }
            return objects;
        }
    }
}
